var Game = function(opt, parent) {
	this.parent = parent;
	this.data = _.extend({
		realWidth: 640,
		realHeight: 960
	}, opt);

	this.el = {
		'room': $("#room"),
		'infoPage': $("#info"),
		'levelList': $("#levelList"),

		// btn
		'resume': $(".resume"),
		'restart': $(".restart"),
		'back': $(".back"),
		'nextLv': $('.nextLv')
	};

	this.status = false;

	// bubble data
	this.bubbleW = 64;
	this.bubbleH = 64;
	this.bubbleV = 25;
	this.bubbleList = [];

	// 下压 距离 速度 index 时间间隔
	this.compressorOffset = 0;
	this.compressorV = 15;
	this.compressorIdx = 0;
	this.compressorD = 10; // 时间间隔

	// 游戏内数据
	this.gameTime = 0;

	// 竖排球的数量 12个球
	this.ball_cols = 13;

	// 小球是否在动画中
	this.bubbleAnim = false;

	// 小球石头概率 暂时不能发射石头
	this.stoneEnable = false;
	this.stoneOdds = 0.1;
	this.stone_max = 5;
	this.stone_cur = 0;

	//暂停
	this._pause = false;

	// 需要消除的bubble
	this.bubbleToDisappear = [];

	this.init();
}

Game.prototype = {
	init: function() {
		if (this.inited) return;
		this.inited = true;
		console.log('关卡==>', this.data.level);

		// create canvas
		$('#room').append('<canvas id="stage" width="640" height="960"></canvas>');
		this.el.canvas = $("#stage");

		this.stage = new createjs.Stage('stage');
		createjs.Touch.enable(this.stage, true);

		this.el.canvas.css({
			width: this.data.pageW,
			height: this.data.pageH
		});

	},

	createEls: function() {
		console.log('create el');
		// bubble container
		this.bubbleContainer = new createjs.Container();
		this.bubbleContainer.x = 64;
		this.bubbleContainer.y = 100;
		this.bubbleContainer.width = 512;
		this.bubbleContainer.height = 740;
		this.stage.addChild(this.bubbleContainer);

		// text
		this.FPStxt = new createjs.Text("FPS : ", "22px Arial", "#fff");
		this.FPStxt.x = this.stage.canvas.width - 400;
		this.FPStxt.y = 20;

		this.TIMEtxt = new createjs.Text("0", "28px Arial", "#FB8A3B");
		this.TIMEtxt.x = 67;
		this.TIMEtxt.y = 18;

		// btn pause
		this.pauseBtn = new createjs.Bitmap(Global.imgSource['btn-pause']);
		this.pauseBtn.x = this.stage.canvas.width - 100;
		this.pauseBtn.y = 0;
		this.pauseBtn.cursor = "pointer";
		this.pauseBtn.width = 72;
		this.pauseBtn.height = 70;

		// 炮台
		// this.cannon = new createjs.Bitmap(Global.imgSource['cannon']);
		// this.cannon.x = this.stage.canvas.width/2 + 41;
		// this.cannon.y = this.stage.canvas.height - 80;
		// this.cannon.width = 82;
		// this.cannon.height = 130;
		// this.cannon.rotation = 180;
		var img = new Image();
		img.src = Global.imgSource['bomb'];

		this.spriteSheet = new createjs.SpriteSheet({
			images: [img],
			frames: {
				width: 140,
				height: 140
			},
			animations: {
				bomb: [0, 11]
			}
		});

		//compressor 下压线
		this.compressor = new createjs.Bitmap(Global.imgSource['compressor']);
		this.compressor.x = 2;
		this.compressor.y = -40;
		this.compressor.width = 502;
		this.compressor.height = 40;

		this.bubbleContainer.addChild(this.compressor);

		this.stage.addChild(this.FPStxt, this.TIMEtxt, this.pauseBtn);
		//this.stage.addChildAt( this.cannon ,0 );

		this.initEvent();
	},

	initEvent: function() {
		var me = this;
		this.pauseBtn.on('mousedown', function(e) {
			me.pause.call(me);
		});

		if (this.e_inited) return;
		this.e_inited = true;

		this.stage.on('stagemouseup', function(e) {
			if (!me.bubbleAnim && !me._pause) {
				me.bubbleAnim = true;
				me.bubbleList.push(me.bubble1);
				me.bubble1.shoot(e.stageX, e.stageY, function(bubble) {
					if (bubble.get('type') != 'stone') {
						me.checkDisappear.call(me, bubble);
					} else {
						me.checkGameover();
					}
				});
				me.drawBubble.call(me, 1);
			}
		});

		this.el.resume.on('click', function() {
			me.resume.call(me);
		});

		this.el.restart.on('click', function() {
			console.log('resart');
			me.reset.call(me);
			me.start.call(me);
		});

		this.el.back.on('click', function() {
			me.back.call(me);
		});

		this.el.nextLv.on('click', function() {
			me.nextLv.call(me);
		});

	},

	start: function() {
		console.log('game start!!!');
		this.el.levelList.hide();
		this.el.room.show();
		this.status = true;
		var me = this;
		this.el.room.show();
		this.createEls();

		// 初始化地图
		this.initMap();

		// 监听tick
		createjs.Ticker.setPaused(false);
		if (!createjs.Ticker.hasEventListener('tick')) {
			createjs.Ticker.setFPS(60);
			createjs.Ticker.on("tick", function() {
				if (!me._pause) {
					me.showFPS.call(me);
					me.stage.update();
				}
			});
		}

		// 绘制新球
		// 1 最新的 准备发射的球
		// 2 等待区 下一发就是他
		this.drawBubble(2);
		this.drawBubble(1);

		// 开始 标记
		this.startTimer();


	},

	drawBubble: function(type) {
		if (type === 2) {
			var type;
			if (this.stoneEnable && this.stone_cur < this.stone_max) {
				type = Math.random() < this.stoneOdds ? 'stone' : _.sample(this.bubbleTypeList);
				if (type == 'stone') {
					this.stone_cur++;
				}
			} else {
				type = _.sample(this.bubbleTypeList);
			}

			var bubble = new Bubble({
				x: 44,
				y: this.bubbleContainer.height - 10,
				width: this.bubbleW,
				height: this.bubbleH,
				v: this.bubbleV,
				parent: this,
				bubbleList: this.bubbleList,
				type: type,
				map: this.map
			});

			this.bubbleContainer.addChild(bubble.el);
			this.bubble2 = bubble;
		} else {
			if (!this.bubble2) {
				this.drawBubble(2);
			}
			var me = this,
				bX = this.bubbleContainer.width / 2 - this.bubbleW / 2,
				bY = this.bubbleContainer.height - this.bubbleH / 2;

			this.bubble1 = this.bubble2;

			// this.bubble1.el.x = bX;
			// this.bubble1.el.y = bY;

			// me.drawBubble(2);

			// return;

			createjs.Tween.get(this.bubble1.el).to({
				x: bX,
				y: bY
			}, 150 , createjs.Ease.backOut).call(function() {
				me.drawBubble(2);
			});

		}
	},

	initMap: function() {
		// 地图所有球的类型集合
		// 在生成下一个球的时候用到
		var me = this;

		this.levelData = _.clone(Global.lvList[this.data.level]);
		this.map = [
			[],
			[],
			[],
			[],
			[],
			[],
			[],
			[],
			[],
			[],
			[],
			[],
			[]
		];
		this.bubbleTypeList = [];

		_.each(this.levelData.map, function(line, k) {
			_.each(line, function(bType, i) {
				if (!bType) return;
				var x = i * me.bubbleW + (k % 2 ? me.bubbleW / 2 : 0);
				var y = k * me.bubbleW * Math.sqrt(3) / 2;
				var newBubble = new Bubble({
					x: x,
					y: y,
					width: me.bubbleW,
					height: me.bubbleH,
					v: me.bubbleV,
					parent: me,
					bubbleList: me.bubbleList,
					type: bType,
					map: me.map
				});
				newBubble.posInfo = {
					x: x,
					y: y,
					xIdx: i,
					yIdx: k
				};
				if (bType != 'stone') me.bubbleTypeList.push(bType);
				me.bubbleContainer.addChild(newBubble.el);
				me.map[k][i] = newBubble;
				me.bubbleList.push(newBubble);
			});
		});

		_.each(me.bubbleList, function(bubble, k) {
			bubble.checkSiblings();
		});

		console.log('绘制地图', this.bubbleContainer, this.stage);
	},

	showFPS: function() {
		var fps = createjs.Ticker.getMeasuredFPS().toString().substring(0, 4);
		this.FPStxt.text = "FPS : " + fps;
	},

	checkDisappear: function(bubble) {
		// 通过一个源泡泡 找到相邻的同色兄弟
		this.findBro(bubble);

		if (this.bubbleToDisappear.length > 2) {
			// 消除同色
			this.disappearBubbles();
			// 消除没有支点的
			this.checkFallDown();
		}

		this.bubbleToDisappear.length = 0;

		//根据容器的球来更新发射求列表
		this.updateBubbleTypeList();

		// 检查游戏是否结束
		this.checkGameover();
	},

	// 递归找出bubble的兄弟
	findBro: function(bubble) {
		var me = this;
		_.each(bubble.hitBubbles, function(b) {
			if (!_.isString(b) && _.indexOf(me.bubbleToDisappear, b.get('id')) == -1 && b.get('type') == bubble.get('type')) {
				me.bubbleToDisappear.push(b.get('id'));
				me.findBro.call(me, b);
			}
		});
	},

	disappearBubbles: function() {
		console.log('--> disappear bubbles', this.bubbleToDisappear);
		var me = this;
		_.each(this.bubbleToDisappear, function(bID) {
			var i, bubble = _.find(me.bubbleList, function(b, idx) {
					if (b.get('id') == bID) {
						i = idx;
						return true;
					}
				});
			bubble.bomb();
			me.removeBubbleFromList.call(me, i);
		});
	},

	removeBubbleFromList: function(idx) {
		this.bubbleList.splice(idx, 1);
	},

	checkFallDown: function() {
		var me = this;
		var fallDown = [];

		var setSilblingLink = function(bubble) {
			bubble.set('hasLinks', 1);
			_.each(bubble.hitBubbles, function(b) {
				if (!_.isString(b) && !b.get("hasLinks")) {
					setSilblingLink(b);
				}
			});
		};

		_.each(this.map, function(list) {
			_.each(list, function(bubble) {
				if (bubble && !bubble.get('hasLinks') && bubble.posInfo.yIdx === 0) {
					bubble.set('hasLinks', 1);
					_.each(bubble.hitBubbles, function(b) {
						if (!_.isString(b) && !b.get("hasLinks")) {
							setSilblingLink(b);
						}
					});
				}
			});
		});

		// 去除没有依靠的
		_.each(this.bubbleList, function(bubble, i) {
			if (!bubble.get('hasLinks')) {
				// 要掉落的球球
				bubble.fallDown();
				fallDown.push(bubble);
			} else {
				bubble.set('hasLinks', false);
			}
		});

		_.each(fallDown, function(bubble) {
			var i = _.indexOf(me.bubbleList, bubble);
			me.removeBubbleFromList.call(me, i);
		});

		console.log('--> left', this.bubbleList.length);
	},

	startTimer: function() {
		var me = this;
		var time = this.TIMEtxt;
		this.gameTimer = setInterval(function() {
			me.gameTime++;
			time.text = me.gameTime;
			me.moveCompressor();
		}, 1000);
	},

	showInfo: function(type, data) {
		this.el.infoPage.fadeIn(10);
		var el = $("#" + type + "Info");
		el.addClass("show");
		if (type == 'gameWin') {
			var html = '';
			el.find(".nextLv")[data.fn]();
			el.find('.time').html(Util.formateTime(this.gameTime));
			_(3).times(function(i) {
				if (i + 1 <= data.lvInfo.star) {
					html += "<i class='star'></i>";
				} else {
					html += "<i></i>";
				}
			});
			el.find(".star-wrap").html(html);
		}
	},

	hideInfo: function(type) {
		this.el.infoPage.find('.dialog').removeClass("show");
		this.el.infoPage.fadeOut(200);
	},

	resume: function() {
		console.log('game resume');
		this.hideInfo('resume');
		this._pause = false;
		this.startTimer();
		createjs.Ticker.setPaused(false);
	},

	reset: function() {
		console.log('game reset');
		this.stone_cur = 0;
		this._pause = false;
		this.hideInfo('resume');
		clearInterval(this.gameTimer);
		this.stage.removeAllChildren();
		this.bubbleList.length = 0;
		this.levelData = null;
		this.bubbleTypeList.length = 0;
		this.map.length = 0;
		this.bubbleAnim = false;
		this.gameTime = 0;
		this.compressorOffset = 0;
		this.compressorIdx = 0;
	},

	back: function() {
		console.log('game back');
		this.status = false;
		this.reset();
		this.parent.resetGame();
	},

	nextLv: function() {
		console.warn('next level',this.data.level);
		var nextLv = this.data.level + 1;
		this.data.level = nextLv;
		this.reset();
		this.start();
	},

	pause: function() {
		console.log('game pause');
		this._pause = true;
		clearInterval(this.gameTimer);
		this.showInfo('pause');
	},

	stop: function() {
		console.log('game stop');
		this._pause = true;
		clearInterval(this.gameTimer);
	},

	//  stage resize
	resize: function(wh) {
		this.status && this.pause();
		this.el.canvas.width(wh.w);
		this.el.canvas.height(wh.h);
		this.data.pageW = wh.w;
		this.data.pageH = wh.h;
	},

	updateBubbleTypeList: function() {
		var me = this;
		this.bubbleTypeList.length = 0;

		_.each(this.bubbleList, function(bubble) {
			if (bubble.get('type') != 'stone') {
				me.bubbleTypeList.push(bubble.get('type'));
			}
		});
	},

	// 检查游戏结束与否
	checkGameover: function() {
		console.log('check game over', this.bubbleContainer);

		this.moveCompressor(true);

		if (this.bubbleList.length === 0) {
			var me =this;
			setTimeout(function() {
				me.gameWin.call(me);
			}, 500);

			return;
		}

		this.bubbleAnim = false;
	},

	// 移动小墩子
	moveCompressor: function(moveover) {
		if (this.bubbleAnim && !moveover) return;
		var me = this;
		var idx = Math.floor(this.gameTime / this.compressorD);
		var gameLost = false;

		if (idx > this.compressorIdx) {

			this.compressorOffset = this.compressorV * idx;
			this.compressor.y = this.compressorOffset - this.compressor.height;
			this.compressorIdx = idx;

			_.each(this.bubbleList, function(bubble) {
				if (bubble.posInfo) {
					bubble.el.y = bubble.posInfo.y + me.compressorOffset;
				}
			});
		}


		// 检测距离
		_.each(this.bubbleList, function(bubble) {
			if (bubble.posInfo) {
				var yIdx = Math.round(bubble.el.y / Math.sqrt(3) / me.bubbleH * 2);
				if (yIdx >= (me.ball_cols - 1)) gameLost = true;
			}
		});

		gameLost && me.gameLost();
	},

	gameWin: function() {
		this.stop();
		var fn = 'show';

		// 获取ls存储的信息
		var lvDataObj = localStorage.getItem('lvData');
		lvDataObj = JSON.parse(lvDataObj);
		var lvIdx_s = parseInt(localStorage.getItem('lv'));

		// 本关得的星星
		var gameStar = 3 - _.sortedIndex(this.levelData.star, this.gameTime);

		// 本关的历史记录
		var lv_s = lvDataObj[this.data.level];
		lv_s = lv_s || {};

		// 比较历史记录
		if (!lv_s.time || lv_s.time > this.gameTime) {
			lv_s.time = this.gameTime;
		}

		if (!lv_s.star || lv_s.star < gameStar) {
			lv_s.star = gameStar;
		}

		// 存储新记录
		lvDataObj[this.data.level] = lv_s;
		localStorage.setItem('lvData', JSON.stringify(lvDataObj));

		// 开通下一关 如果还有下一关或者下一关没开通
		if (Global.lvList[this.data.level + 1] && lvIdx_s < this.data.level + 1) {
			localStorage.setItem('lv', this.data.level + 1);
		}

		if (!Global.lvList[this.data.level + 1]) {
			// 没有下一关
			// TODO
			console.log('没有下一关了');
			fn = 'hide';
		}

		this.showInfo('gameWin', {
			lvInfo: lv_s,
			fn: fn
		});

	},

	gameLost: function() {
		this.stop()
		this.showInfo('gameLost');
	}
};
